﻿using UnityEngine;
using System.Collections.Generic;

public class ViewProxy
{
    private static string uiPath = "prefab/ui/";

    protected enum LoadingState
    {
        None = 0,
        Loading = 1,
        Finish = 2,
        Failed = 3,
    }

//    protected System.Type _windowType;
//    public System.Type WindowType
//    {
//        get
//        {
//            return _windowType;
//        }
//        set
//        {
//            _windowType = value;
//        }
//    }

    [HideInInspector]
    public int preWindowAction;

    public string winName;

    LuaInterface.LuaTable _luaParam;
	bool _initCalled = false;
	bool _inited = false;
    public System.Action<ViewProxy> initedCallback;

    protected IUIAnimElem closeAnimElem;
    protected bool closeAnimForward;

    IUIAnimElem _animParam;
    bool _animReverse;
    System.Action _animCallBack;


        protected WindowManager _parentWinManager;
    public WindowManager parentWinManager
    {
        set
        {
            _parentWinManager = value;
        }
        get
        {
            return _parentWinManager;
        }
    }

    public void Init()
    {
        Init(null);
    }

    public void Init(LuaInterface.LuaTable luaParam)
    {
        IUIAnimElem anim = null;
        bool animForward = true;

        if(RootWindowManager.globalAnim != null)
        {
            anim = RootWindowManager.globalAnim;
            animForward = RootWindowManager.globalAnimForward;
        }
        
        this.Init(luaParam, anim, animForward);
    }

    public void Init(LuaInterface.LuaTable luaParam, IUIAnimElem animParam)
    {
        this.Init(luaParam, animParam, true);
    }

    public void Init(LuaInterface.LuaTable luaParam, IUIAnimElem animParam, bool animReverse)
	{
		_initCalled = true;
        if (_inited)
        {
            return;
        }

        _luaParam = luaParam;
		if (win == null)
        {
            this.PlayAnimAndHidePreWindow(animParam, animReverse);
			return;
		}

		_inited = true;
        win.Init (_luaParam);

        if (_luaParam != null)
        {
            _luaParam.Dispose();
            _luaParam = null;
        }

        if (this.initedCallback != null)
        {
            initedCallback(this);
        }

        this.PlayAnimAndHidePreWindow(animParam, animReverse);
	}



    // Dictionary<string, object> _paramMap;
    // public void SetParam(Dictionary<string, object> paramMap)
    // {
    //     if (win != null)
    //     {
    //         win.SetParam(paramMap);
    //     }
    //     else
    //     {
    //         _paramMap = paramMap;
    //     }
    // }

    // public void SetParam(string key, object value)
    // {
    //     if (win != null)
    //     {
    //         win.SetParam(new Dictionary<string, object>(){{key, value}});
    //     }
    //     else
    //     {
    //         if (_paramMap == null)
    //         {
    //             _paramMap = new Dictionary<string, object>();
    //         }
    //         _paramMap.Add(key, value);
    //     }
    // }

    public void SetAnim(IUIAnimElem animParam, bool animReverse, System.Action callBack)
    {
        if (win != null && _inited)
        {
            if (animParam != null)
            {
                win.SetAnim(animParam, animReverse, callBack);
            }
        }
        else
        {
            _animParam = animParam;
            _animReverse = animReverse;
            _animCallBack = callBack;
        }
    }

    public IUIAnimElem GetCloseAnim(out bool forward)
    {
        forward = this.closeAnimForward;
        return this.closeAnimElem;
    }

    public void PlayAnimAndHidePreWindow(IUIAnimElem animElem, bool forward)
    {
        this.PlayAnimAndHidePreWindow(animElem, forward, animElem, !forward);
    }

    public void PlayAnimAndHidePreWindow(IUIAnimElem animElem, bool forward, IUIAnimElem closeAnimElem, bool closeAnimForward)
    {
        this.closeAnimElem = closeAnimElem;
        this.closeAnimForward = closeAnimForward;

        int preWinAction = preWindowAction;

        this.parentWinManager.PlayAnimAndHidePreWindow(animElem, forward, null, true, preWinAction);
    }

    private string getPrefabName()
    {
//        object[] attrs = WindowType.GetCustomAttributes(typeof(WindowPrefabAttribute), true);
//        for (int i = 0; i < attrs.Length; i++)
//        {
//            WindowPrefabAttribute a = attrs[i] as WindowPrefabAttribute;
//            return a.t.Name;
//        }
//        return WindowType.Name;

        return this.winName;
    }

    protected bool _isActive = false;
    public virtual bool isActive
    {
        get { return _isActive; }
        set
        {
            //如果UI需要强制刷新active  可以将这个判断去掉
            if (_isActive == value)
                return;
            _isActive = value;
            if (win == null)
            {
                loadingState = LoadingState.Loading;
                ResourceManager.LoadAssetAsync(uiPath + getPrefabName(), LoadComplete);
            }
            else
            {
                win.gameObject.SetActive(_isActive);
            }
        }
    }
    
    protected LoadingState loadingState = LoadingState.None;
    public bool isLoadComplete { get { return loadingState == LoadingState.Finish; } }

    protected bool isDestroyed;
	public Window win;
    public object winData;
    public Bounds uiBounds = new Bounds(Vector3.zero, Vector3.zero);
    protected Vector3 localPos = Vector3.zero;

    GameObject _parentGo;
    public GameObject parentGo
    {
        get
        {
            return _parentGo;
        }
        set { _parentGo = value; }
    }

    protected virtual void LoadComplete(object obj, string path)
    {
        if (obj == null)
        {
            Debug.LogError("加载" + winName + "失败");
            return;
        }
        InitUIGameObject(obj);
        InitView();
    }

    protected virtual void Refresh()
    { }

    protected virtual void InitView()
    { }

    public void UpdateUI()
    {
        if (isLoadComplete)
            Refresh();
    }

    protected virtual void InitUIGameObject(object obj)
    {
        if (isDestroyed)
        {
            return;
        }
            
        GameObject prefab = obj as GameObject;
        if (obj == null || prefab == null)
        {
            throw new System.Exception("load prefab failed: InitUIGameObject: " + (obj == null) + "  " + (prefab == null) + "  " + uiPath + getPrefabName());
        }
        GameObject uiGameObject = NGUITools.AddChild(parentGo, prefab);


        {
            this.win = uiGameObject.GetComponent<Window>();
            List<Component> wins = uiGameObject.GetComponentsEx(typeof(LuaData));
            for (int i = 0; i < wins.Count; i++)
            {
                var w = wins[i] as LuaData;
                if (w.GetType().Name != winName)
                {
                    if (winData == null)
                    {
                        winData = w;
                    }
                    else
                    {
                        GameObject.Destroy(w);
                    }
                }
                else
                {
                    if (winData != null)
                    {
                        GameObject.Destroy(winData as Component);
                        win = null;
                    }
                    winData = w;
                }
            }
            wins.RecycleToListPool();
        }

        if(winData == null)
        {
            List<Component> wins = uiGameObject.GetComponentsEx(typeof(SerializeEx.SerializableFieldContainerBehaviour));
            for (int i = 0; i < wins.Count; i++)
            {
                SerializeEx.SerializableFieldContainerBehaviour w = wins[i] as SerializeEx.SerializableFieldContainerBehaviour;
                if (w.GetFieldDictionary().className != winName)
                {
                    if (winData == null)
                    {
                        winData = w;
                    }
                    else
                    {
                        GameObject.Destroy(w);
                    }
                }
                else
                {
                    if (winData != null)
                    {
                        GameObject.Destroy(winData as Component);
                        win = null;
                    }
                    winData = w;
                }
            }
            wins.RecycleToListPool();
        }


        win.SetLuaCtrlName("View/" + winName + "Ctrl");

        win.proxy = this;
        uiGameObject.SetActive(_isActive);
        uiBounds = NGUIMath.CalculateRelativeWidgetBounds(uiGameObject.transform, true);
        uiGameObject.transform.localPosition = localPos;
        loadingState = LoadingState.Finish;

        if (win == null)
        {
            Debug.LogError("need inherit from window class: " + winName);
        }
        else
        {
			if (_initCalled)
			{
                Init (_luaParam, _animParam, _animReverse);
			}

            // if (_paramMap != null)
            // {
            //     win.SetParam(_paramMap);
            //     _paramMap = null;
            // }

            // if (_animParam != null)
            // {
            //     win.SetAnim(_animParam, _animReverse, _animCallBack);
            // }
        }
    }

    public virtual void Destroy()
    {
        if (win != null)
        {
            GameObject.Destroy(win.gameObject);
            win = null;
        }
        else
        {
            ResourceManager.CancelAsyncTask(uiPath + getPrefabName(), LoadComplete);
        }

        isDestroyed = true;
    }

    public virtual void SetPosition(float x, float y)
    {
        localPos.x = x;
        localPos.y = y;
        if (isLoadComplete)
            win.gameObject.transform.localPosition = localPos;
    }

    #region 工具函数

    protected T GetComponent<T>(string path) where T : MonoBehaviour
    {
        var tChild = win.gameObject.transform.Find(path);
        var com = tChild.GetComponent<T>();
        return (T)com;
    }

    protected GameObject GetGameObject(string path)
    {
        Transform t = win.gameObject.transform.Find(path);
        return ( null == t ) ? null : t.gameObject;
    }
    #endregion

    public virtual void Close()
    {
        
    }

    public virtual void Close(IUIAnimElem animElem, bool forward)
    {
        
    }
}

